package com.leyou.order.service;

import com.leyou.common.auth.domain.UserHolder;
import com.leyou.common.exception.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.IdWorker;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.order.domain.Order;
import com.leyou.order.domain.OrderDetail;
import com.leyou.order.domain.OrderLogistics;
import com.leyou.order.dto.*;
import com.leyou.order.enums.OrderStatusEnum;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderLogisticsMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.utils.PayHelper;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@Service
@Transactional
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderDetailMapper detailMapper;

    @Autowired
    private OrderLogisticsMapper logisticsMapper;

    /**
     * 分布式主键
     */
    @Autowired
    private IdWorker idWorker;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private UserClient userClient;

    @Autowired
    private PayHelper payHelper;
    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final String WX_PAY_URL_PRE="WX:PAY:URL:PRE";

    public Long buildOrder(OrderDTO orderDTO) {
        try {
            //生成订单id
            Long orderId = idWorker.nextId();
            //创建订单对象
            Order order = new Order();
            order.setOrderId(orderId);
            order.setStatus(OrderStatusEnum.INIT.value());
            order.setUserId(UserHolder.getUserId());//待完善，要写拦截器
            order.setSourceType(2);//订单来源
            order.setPostFee(0L);//邮费，包邮
            order.setPaymentType(1);//支付类型
            order.setInvoiceType(0);//发票类型
            order.setActualFee(1L);//实付金额，应该是总金额减去活动金额，这里为了测试支付，先写一分钱

            //得到购物车信息
            List<CartDTO> carts = orderDTO.getCarts();
            //把list列表结构的购物车集合改成map结构
            Map<Long, Integer> cartsMap = carts.stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
            //通过购物车信息得到sku的id的集合
            List<Long> skuIds = carts.stream().map(CartDTO::getSkuId).collect(Collectors.toList());
            //根据sku的Id的集合查询出sku对象的集合
            List<SkuDTO> skuDTOS = itemClient.findSkusBySkuIds(skuIds);
            //遍历skuDTOS集合，搜集每一个对象中价格乘以购物车中的数量，最后将所有的结构相加
            Long totalFee = skuDTOS.stream().mapToLong(skuDTO -> skuDTO.getPrice() * cartsMap.get(skuDTO.getId())).sum();
            //设置总金额
            order.setTotalFee(totalFee);

            //保存订单
            orderMapper.insertSelective(order);

            //new一个订单详情的集合
            List<OrderDetail> list = new ArrayList<>();
            //循环sku的集合并给其转成订单详情集合
            skuDTOS.forEach(skuDTO -> {
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setId(idWorker.nextId());
                orderDetail.setOrderId(orderId);
                orderDetail.setSkuId(skuDTO.getId());
                orderDetail.setTitle(skuDTO.getTitle());
                orderDetail.setPrice(skuDTO.getPrice());
                orderDetail.setOwnSpec(skuDTO.getOwnSpec());
                orderDetail.setImage(StringUtils.substringBefore(skuDTO.getImages(), ","));
                orderDetail.setNum(cartsMap.get(skuDTO.getId()));
                orderDetail.setCreateTime(new Date());
                orderDetail.setUpdateTime(new Date());
                list.add(orderDetail);
            });
            //保存订单详情列表
            detailMapper.insertList(list);

            //获取物流信息
            AddressDTO addressDTO = userClient.queryAddressById(UserHolder.getUserId(), orderId);
            //将dto转成物流对象
            OrderLogistics orderLogistics = BeanHelper.copyProperties(addressDTO, OrderLogistics.class);
            //设置订单id
            orderLogistics.setOrderId(orderId);
            //保存物流信息
            logisticsMapper.insertSelective(orderLogistics);

            //减库存
            itemClient.minusStock(cartsMap);
            return orderId;
        }catch (Exception e){
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

    }

    public OrderVO queryOrderById(Long id) {
        //查询订单
        Order order = orderMapper.selectByPrimaryKey(id);
        //将订单转成vo
        OrderVO orderVO = BeanHelper.copyProperties(order, OrderVO.class);

        //根据订单id查询订单详情列表
        OrderDetail record = new OrderDetail();
        record.setOrderId(id);
        List<OrderDetail> orderDetails = detailMapper.select(record);
        //转成dto
        List<OrderDetailVO> orderDetailVOS = BeanHelper.copyWithCollection(orderDetails, OrderDetailVO.class);
        //设置详情列表值
        orderVO.setDetailList(orderDetailVOS);

        //根据订单id查询物流信息
        OrderLogistics lRecord = new OrderLogistics();
        lRecord.setOrderId(id);
        OrderLogistics orderLogistics = logisticsMapper.selectOne(lRecord);
        //转dto
        OrderLogisticsVO orderLogisticsVO = BeanHelper.copyProperties(orderLogistics, OrderLogisticsVO.class);
        //设置物流信息
        orderVO.setLogistics(orderLogisticsVO);
        return orderVO;
    }


    public String createWxPayUrl(Long id) {
        //先从redis中获取支付链接
        String payUrl = redisTemplate.opsForValue().get(WX_PAY_URL_PRE + id);
        //如果有返回
        if (StringUtils.isNotBlank(payUrl)) {
            log.info("【微信统一下单】重redis中获取连接成功");
            return payUrl;
        }
        //根据订单id查询订单对象
        Order order = orderMapper.selectByPrimaryKey(id);
        //判断当前订单是否已经支付
        if (!order.getStatus().equals(OrderStatusEnum.INIT.value())) {
            log.info("【微信统一下单】不要重复支付");
            throw new LyException(502,"【微信统一下单】不要重复支付");
        }
        //调用获取支付链接的工具类
        String codeUrl = payHelper.createWxPayUrl(id, order.getActualFee());
        //将支付的链接放入redis中
        redisTemplate.opsForValue().set(WX_PAY_URL_PRE+id,codeUrl,2, TimeUnit.HOURS);
        log.info("【微信统一下单】成功返回支付链接");
        return codeUrl;
    }

    public Integer queryOrderStatus(Long id) {
        Order order = orderMapper.selectByPrimaryKey(id);
        if (order == null) {
            log.info("【二维码支付失败】查询订单失败，没有找到对应订单！订单号为:{}", id);
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return order.getStatus();
    }

    public void checkWxReturnMsg(Map<String, String> resp) {
        log.info("【验证微信支付回调】开始！");
        //验证通信标识和业务标识
        payHelper.checkWxReturnCode(resp);
        //获取订单id
        Long out_trade_no = Long.valueOf(resp.get("out_trade_no"));
        // 获取支付金额
        Long total_fee = Long.valueOf(resp.get("total_fee"));
        //根据订单id查询订单
        Order order = orderMapper.selectByPrimaryKey(out_trade_no);
        if (order == null) {
            log.info("【验证微信支付回调】订单不存在！");
            throw new LyException(502,"【验证微信支付回调】订单不存在！");
        }
        //判断金额是否一致
        if (!total_fee.equals(order.getActualFee())) {
            log.info("【验证微信支付回调】金额不一致！");
            throw new LyException(502, "【验证微信支付回调】金额不一致！");
        }
        //修改订单状态
        Order record = new Order();
        record.setOrderId(out_trade_no);
        record.setStatus(OrderStatusEnum.PAY_UP.value());
        int count = orderMapper.updateByPrimaryKeySelective(record);
        if (count != 1) {
            log.info("【验证微信支付回调】更新状态失败！");
        }
        log.info("【验证微信支付回调】正常结束！");
    }
}
